package screen_calibration;
/**
 * Created on 18/05/2005
 *	
 * Project goal:
 * 			Calibrate CRT screen and estimate the screen primeries values.
 * 
 * Created for Hagit Hel-Or
 * 			Imaging Science course final project
 * 
 * Created by:
 * @author Alex Frid alex.frid@gmail.com; Ran Dror				
 */

import screen_calibration.Jama.*;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ComponentOrientation;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Scrollbar;
import java.awt.event.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.geom.Line2D;
import java.awt.image.RGBImageFilter;
import java.io.FileWriter;
import java.io.IOException;


import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.swing.border.EtchedBorder;

// import sun.security.krb5.internal.i;

/**
 * The main class of the program.
 * Open a UI for screen calibratiom..
 * This class can be activated from Matlab program for more
 * complex data manipulation.
 * 
 * Note 1:
 * Activating the program as Application:
 * 	To activate the programm as application you should do 
 * 	the following steps:
 * 	1) Change the Calibrate class from "extends JApplet" to "extends JFrame"
 * 	2) Add the following constructor to this file:
 * 		public Calibrate(){
 * 			super();
 * 			init();
 * 		}
 * 	3)Add the following main function:
 * 		public static void main(Strings[] args){
 * 			Calibrate cal = new Calibrate();
 * 			cal.setVisible(true);
 * 			cal.repaint();
 * 		}
 * 
 * Note 2:
 * Activating the program from Matlab:
 * 	1) Change the programm to Application as described in Note 1.
 * 	2) If you use Matlab 7:
 * 		addd the main class path to the matlab java path with the function
 * 		javaaddpath 'your path'
 * 	   Else if you using matlab 6.5
 * 		In that version and the earlier versions there is no support for dinamic java path
 * 		so you need to find the file classpath.txt in matlab installation library and to add the 
 * 		path manually. The disadvantage is that the class will load when the matlab starts.
 * 		So changing the content of the file (recompiling) will affect just after the matlab will 
 * 		restart and reload the java class path. 		 
 * 	3) Create the programm object:
 * 		obj = javaObject(object name)
 * 	4) Set the object visible:
 * 		obj.setVisible(true);
 * 	5) From now you can call all the bublic functions from the java object
 * 		note: a) there is attached matlab file for example
 * 			  b) all the function that related to that process are well documented
 * 	
 * 	Activating the matlab from java
 * 		This option is less supported and there foere i dont know what versions of matlab supports this fiture
 * 		but can be usefull in some cases.
 * 
 * 		1) Add to this java project lmi.jar file as "extended jar" tis file is 
 * 			short of Java-Matlab Interface.
 * 		2) import JMI.Matlab;
 * 		3) from now on you can create an Java objects thet yuse matlab engene
 * 			example: Matlab m = new Matlab();
 * 					 m.conv(...); // use the object like in matlab 
 */
public class Calibrate extends /*JFrame*/  JApplet/**/ {
	
	/** Handles the action events */
	private ActionEventHandler actHandle;
	
	/** Handles the sliders events */
	private AdjustmentEventListener adjHandle;
	
	/** Handles Component events */
	private ComponentEventListener comHandle;
	
	/** the color and gamma sliders */
	private JScrollBar slider1, slider2, slider3, gammaSlider;
	
	/** Canvas for the gamma check */ 
	private GammaCanvas ditheredCanvas, gammaCanvas;
	
	/** Canvas for the xyx gamut image */
	private CanvasLabel canvasLabel;
	
	// Slider values storred here
	private JLabel colorNumber1, colorNumber2, colorNumber3;
	
	// Label that shows the gamma 
	private JLabel gammaLabelTab1, gammaLabelTab2;
	
	// Gui choose tabs
	private JPanel primariesEstimationTab, gammaCorrectionTab, spectrumTab,
		blackPointTab, rgbGamaTab;
	
	// Mixed rgb color presenting panel
	private JPanel colorBlock, emptyColorblock;
	
	// Tabbed pane - contains all gui components
	private JTabbedPane mainPane;
	
	// Controll buttons
	private JButton next, back, resetSliders, compute, setXYZ;
	
	// Data structures
	private double[][] xyzValues, rgbValues, primariesValues;
	
	// Stores the gamma value
	private double gammaValue;
	
	// These text fields presents the data collected from the user on the screen
	private JTextField[][] xyzField, rgbField, primariesField;
	
	// Counts the quantity of checks inserted by the user in to rgb array
	private int rgbDataCount = 0;
	
	/** Flag indicator that indicates wheter the data accepted from the user 
	 *  is ready or not */
	private boolean dataReady = false;
	
	private String newLine = new String("\n");
	
	/** Holds the gamma image */
	private ImageViewer rgbGamaImage;
	
	/** Text area for color gamma tab masseges */
	private JTextArea textArea;
	
	// the size of the matrices
	private int mHeight = 3;
	private int mWidth = 3;
	
	/** The path for the images in the program */
	private String imagePath;
	
	/** Container for gui components */
	Container c;
	
	/** Uncomment this lines if you want to activate the project as Application */
	/**
	// Default c'tor
	public Calibrate(){
	    super("screen Calibration. by Alex&Ran");
	    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	    init();
	}
	
	// Main method
	public static void main(String[] args){
	    Calibrate c = new Calibrate();
	    
	    Dimension d = new Dimension(650, 440);
	    c.setSize(d);
	    c.setPreferredSize(d);
	    c.setMaximumSize(d);
	    c.setMinimumSize(d);
	    
	    c.setVisible(true);
	}
	*/
	
	/** Applet initialization */
	public void init(){
		
		// set preferred size of the applet window 
		setSize(650,440);     	
		
		// Set a swing gui container 
		c = getContentPane();
		
		// Set the layout manager of the main frame
		c.setLayout(new GridLayout(1, 1));
		
		// set the images files path
		imagePath = /*getCodeBase() + */"images/";
		
		// Define all the tabs 
		primariesEstimationTab = new JPanel(new GridLayout(2, 1));
		gammaCorrectionTab = new JPanel(new GridLayout(1, 1));
		spectrumTab = new JPanel(new GridLayout(1, 1));
		blackPointTab = new JPanel(new GridLayout(1, 1));
		rgbGamaTab = new JPanel(new BorderLayout());
		
		// set initial gamma
		gammaValue = 2.2;
		
		// Construct tabbed pane 
		mainPane = new JTabbedPane();
		mainPane.addTab("Black & White point calibration ", blackPointTab);
		mainPane.addTab("Gamma Correction", gammaCorrectionTab);
		mainPane.addTab("RGB Gamma consistence test", rgbGamaTab);
		mainPane.addTab("Primaries estimation", primariesEstimationTab);
		mainPane.addTab("Spectrum View", spectrumTab);
		
		// Add to the main container
		c.add(mainPane);
		
		//build the event handlers
		actHandle = new ActionEventHandler();
		adjHandle = new AdjustmentEventListener();
		comHandle = new ComponentEventListener();    
		
		xyzValues = new double[mHeight][mWidth];
		rgbValues = new double[mHeight][mWidth];
		primariesValues = new double[mHeight][mWidth];
		
		// build the gui tabs 
		buildTab1(primariesEstimationTab);
		buildTab2(gammaCorrectionTab);
		buildTab3(spectrumTab);
		buildTab4(blackPointTab);
		buildTab5(rgbGamaTab);
		
		// set the image in the color gamma tab
		setRgbGamaImage();
	}
	
	/** Build RGB Gamma check tab */
	private void buildTab5(JPanel p){
		
		rgbGamaImage = new ImageViewer(imagePath + "RgbGama_" + 1 + "_" + 0 + ".png");
		
		// Add the text area
		textArea = new JTextArea(
				"The image on the left is designed for Gamma: " + gammaValue + 
				" that you calibrated in the previous step." + newLine + 
				"If you see a gray image, and you dont see any colors," +
				"  then the gama value is calibrated and your screen have" +
				" the same gamma values for R,G amd B colors." + newLine +
				"If you can see colors in the image then try to adjust the gamma " +
				"more presisly in the previous step. " + 
				"If you still see colors than you need to calibrate each color " +
				"gamma seperately."
		);
		
		textArea.setFont(new Font("Serif", Font.ITALIC, 16));
		textArea.setLineWrap(true);
		textArea.setWrapStyleWord(true);
				
		JScrollPane areaScrollPane = new JScrollPane(textArea);
		areaScrollPane.setVerticalScrollBarPolicy(
				JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		areaScrollPane.setBorder(BorderFactory.createCompoundBorder(
				BorderFactory.createEmptyBorder(10,8,8,8),
				BorderFactory.createEtchedBorder()));
		
		Dimension d = new Dimension(300, 200);
		areaScrollPane.setPreferredSize(d);
		areaScrollPane.setMaximumSize(d);
		areaScrollPane.setMinimumSize(d);
		areaScrollPane.setSize(d);
		
		p.add(areaScrollPane,BorderLayout.LINE_END);
		p.add(rgbGamaImage,BorderLayout.CENTER);
	}
	
	/** Set the rgb gamma check */
	public void setRgbGamaImage(){
	    
	     
	        
		long gamaRound = (Math.round((float)10*gammaValue));
		
		rgbGamaTab.remove(rgbGamaImage);
		
		rgbGamaImage = new ImageViewer( imagePath +
				"RgbGama_" + gamaRound/10
				+ "_" + gamaRound%10 + ".png");
		
		
		rgbGamaTab.add(rgbGamaImage,BorderLayout.CENTER);
				
		System.out.println(imagePath + "RgbGama_" + gamaRound/10 + "_"
		        + gamaRound%10 + ".png"
				);
		
		// error msg
		String gammaError = new String(" The goal of this step is to verify if " +
				"the Gamma value is equal " + "for R,G and B colors. The Gamma value" +
				" that tou entered is out of the valid range. The Valid range is:" +
				" 1<= Gamma <= 3.");
		
		if(1 > gammaValue ||  gammaValue > 3){
			textArea.setText(gammaError);
		}else{
			textArea.setText("The image on the left is designed for Gamma: " + gammaValue + 
					" that you calibrated in the previous step." + newLine + 
					"If you see a gray image, and you dont see any colors," +
					"  then the gama value is calibrated and your screen have" +
					" the same gamma values for R,G amd B colors." + newLine +
					"If you can see colors in the image then try to adjust the gamma " +
					"more presisly in the previous step. " + 
					"If you still see colors than you need to calibrate each color " +
					"gamma seperately.");
		}
		
	}
	
	/** Builds the priamery estimation UI */
	private void buildTab1(JPanel p){
		JPanel upMain = new JPanel(new GridLayout(1,2));
		
		upMain.add(buildUpLeftInTab2());
		
		upMain.add(buildUpRightInTab2());
		
		p.add(upMain);
		
		p.add(buildDownInTab2());
		
	}
	
	/** Builds the Gamma correction UI */  
	private void buildTab2(JPanel pp){
		
		JPanel mainPanel = new JPanel(new BorderLayout());
		mainPanel.setBackground(Color.GRAY);
		mainPanel.setBorder(BorderFactory.createCompoundBorder(
				BorderFactory.createTitledBorder("Color Chooser"),
				BorderFactory.createEmptyBorder(0, 8, 8, 8)));
		
		JPanel p = new JPanel(new FlowLayout());
		p.setBorder(BorderFactory.createEmptyBorder(20,0,0,0));
		p.setBackground(Color.BLACK);
		//p.setSize(60,120);
		//p.setMaximumSize(new Dimension(60,60));
		//p.setMinimumSize(new Dimension(60,60));
		//p.setPreferredSize(new Dimension(60,60));
		
		Dimension canvasDimension = new Dimension(200,240);
		Dimension canvasSliderDimension = new Dimension(20,
				(int)canvasDimension.getHeight());
		
		ditheredCanvas = new GammaCanvas();
		ditheredCanvas.set_r_Lvl(-1); // make a gray level dithering
		
		ditheredCanvas.setSize(canvasDimension);
		// no such java methods in matlab
		//ditheredCanvas.setMaximumSize(new Dimension(canvasDimension));
		//ditheredCanvas.setMinimumSize(new Dimension(canvasDimension));
		//ditheredCanvas.setPreferredSize(new Dimension(canvasDimension));
		
		
		gammaCanvas = new GammaCanvas();
		gammaCanvas.setGrayLvl(127);
		
		gammaCanvas.setSize(canvasDimension);
		// no such java methods in matlab
		//gammaCanvas.setMaximumSize(new Dimension(canvasDimension));
		//gammaCanvas.setMinimumSize(new Dimension(canvasDimension));
		//gammaCanvas.setPreferredSize(new Dimension(canvasDimension));
		
		gammaSlider = new JScrollBar(JScrollBar.VERTICAL,100, 0, 0, 255);
		gammaSlider.addAdjustmentListener(adjHandle);
		gammaSlider.setToolTipText("Moove the scroll bar till the color on the left " +
		"side match to the color on the right side");
		gammaSlider.setSize(canvasSliderDimension);
		gammaSlider.setMaximumSize(new Dimension(canvasSliderDimension));
		gammaSlider.setMinimumSize(new Dimension(canvasSliderDimension));
		gammaSlider.setPreferredSize(new Dimension(canvasSliderDimension));
		
		// p.add(ditheredCanvas);
		p.add(gammaCanvas);
		p.add(gammaSlider);
		
		gammaLabelTab1 = new JLabel("Your Gamma is: ?");
		gammaLabelTab1.setFont(new Font("TimesRoman", Font.PLAIN, 14));
		gammaLabelTab1.setBackground(Color.GRAY);
		//gammaLabelTab1.setBorder(BorderFactory.createLineBorder(Color.BLUE));
		//gammaLabelTab1.setSize(80,20);
		//gammaLabelTab1.setMaximumSize(new Dimension(80,20));
		//gammaLabelTab1.setMinimumSize(new Dimension(80,20));
		//gammaLabelTab1.setPreferredSize(new Dimension(80,20));
		
		JLabel textPanel = new JLabel("Move the slider until the inner patch ma" +
				"tch in brightness to the background");
		
		mainPanel.add(textPanel, BorderLayout.PAGE_START);
		mainPanel.add(p, BorderLayout.CENTER);
		mainPanel.add(gammaLabelTab1, BorderLayout.PAGE_END);
		
		pp.add(mainPanel);
	}
	
	private void buildTab3(JPanel p){
		Dimension d = new Dimension(300,300);
		
		canvasLabel = new CanvasLabel();
		
		p.add(canvasLabel);
	}
	
	/** Builds the black & white point tab */
	private void buildTab4(JPanel bw){
		ImageIcon icon = createImageIcon(imagePath + "Black&WhitePatch.gif", "description");
		
		System.out.println(imagePath);
		
		//Image image = getImage(getCodeBase(), imagePath + "Black&WhitePatch.gif");
		
		//ImageIcon i = new ImageIcon(image);
		
		JLabel blackPointImage = new JLabel(icon);
		
		blackPointImage.setBorder(BorderFactory.createCompoundBorder(
				BorderFactory.createEtchedBorder(),
				BorderFactory.createEmptyBorder(5,25,5,25)));
		
		Dimension dd = new Dimension(350,250);
		
		// calibration main panel 
		JPanel blackPointCalibration = new JPanel(new GridBagLayout());
		blackPointCalibration.setPreferredSize(dd);
		blackPointCalibration.setSize(dd);
		blackPointCalibration.setMaximumSize(dd);
		blackPointCalibration.setMinimumSize(dd);
		
		blackPointCalibration.setBorder(BorderFactory.createCompoundBorder(
				BorderFactory.createTitledBorder(""),
				BorderFactory.createEmptyBorder(0, 8, 8, 8)));
		
		GridBagConstraints constraints = new GridBagConstraints();
		constraints.gridx = 0;
		constraints.gridy = 0;
		
		// add the black point image
		blackPointCalibration.add(blackPointImage, constraints);
		
		// Add the text area
		JTextArea textArea = new JTextArea(
				"1). Before starting calibrate your screen, it should be on at" +
				" least 30 minutes to stabilize." + newLine +

				"2). Adjust the contrast control to maximum." + newLine +

				"3). Adjust the brightness control to minimum." + newLine +

				"4). Encrease brightness control until you can just distinguish" +
				" the difference between patches marked 0 and 10 sample above " +
				"in same time try to keep patch 0 black as possible. Patch 0 " +
				"should be perfectly black, matching the borders of your monitor," +
				" and patch 10 should be barely visible." + newLine +

				"5). Decrease contrast control until you can just distinguish the" +
				" difference between patches marked 95% and 100% in the above " +
				"sample, If they appear to be the same, then contrast is too " +
				"high." + newLine +

				"6). Check the black point again, go to step 3 if needed."
		);
		
		textArea.setFont(new Font("Serif", Font.ITALIC, 16));
		textArea.setLineWrap(true);
		textArea.setWrapStyleWord(true);
		//textArea.setBorder(BorderFactory.createBevelBorder(4));
		
		JScrollPane areaScrollPane = new JScrollPane(textArea);
		areaScrollPane.setVerticalScrollBarPolicy(
				JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		areaScrollPane.setBorder(BorderFactory.createCompoundBorder(
				BorderFactory.createEmptyBorder(10,8,8,8),
				BorderFactory.createEtchedBorder()));
		
		Dimension d = new Dimension(450, 200);
		areaScrollPane.setPreferredSize(d);
		areaScrollPane.setMaximumSize(d);
		areaScrollPane.setMinimumSize(d);
		areaScrollPane.setSize(d);
		
		constraints.gridx = 0;
		constraints.gridy = 1;
		blackPointCalibration.add(areaScrollPane,constraints);
		
		bw.add(blackPointCalibration);
	}
	
	/** Returns an ImageIcon, or null if the path was invalid. */
	protected static ImageIcon createImageIcon(String path,
			String description) {
		return new ImageIcon(path, description);	
	}
	
	// build the up left panel of tab2
	private JPanel buildUpLeftInTab2(){
		// the main panel
		JPanel upLeft = new JPanel();
		upLeft.setLayout(new BoxLayout(upLeft,BoxLayout.PAGE_AXIS));
		upLeft.setBorder(BorderFactory.createCompoundBorder(
				BorderFactory.createTitledBorder("Color Chooser"),
				BorderFactory.createEmptyBorder(10, 8, 8, 8)));
		//upLeft.setSize(250,150);
		//upLeft.setPreferredSize(new Dimension(250,150));
		//upLeft.setMaximumSize(new Dimension(250,150));
		//upLeft.setMaximumSize(new Dimension(250,150));
		
		// the RED slider panel
		JPanel sliderPanel1 = new JPanel();
		sliderPanel1.setLayout(new BoxLayout(sliderPanel1,BoxLayout.LINE_AXIS));
		sliderPanel1.setSize(250,22);
		sliderPanel1.setPreferredSize(new Dimension(250,22));
		sliderPanel1.setMinimumSize(new Dimension(250,22));
		sliderPanel1.setMaximumSize(new Dimension(250,22));
		
		JLabel clabel = new JLabel("Red");
		clabel.setSize(40,22);
		clabel.setPreferredSize(new Dimension(40,22));
		clabel.setMinimumSize(new Dimension(40,22));
		clabel.setMaximumSize(new Dimension(40,22));
		
		colorNumber1 = new JLabel("100");
		colorNumber1.setSize(40,22);
		colorNumber1.setPreferredSize(new Dimension(40,22));
		colorNumber1.setMinimumSize(new Dimension(40,22));
		colorNumber1.setMaximumSize(new Dimension(40,22));
		
		slider1 = new JScrollBar(Scrollbar.HORIZONTAL, 100, 0, 0, 255);
		slider1.addAdjustmentListener(adjHandle);
		
		sliderPanel1.add(clabel);
		sliderPanel1.add(slider1);
		sliderPanel1.add(colorNumber1);
		
		// the green slider panel
		JPanel sliderPanel2 = new JPanel();
		sliderPanel2.setLayout(new BoxLayout(sliderPanel2,BoxLayout.LINE_AXIS));
		sliderPanel2.setSize(250,22);
		sliderPanel2.setPreferredSize(new Dimension(250,22));
		sliderPanel2.setMinimumSize(new Dimension(250,22));
		sliderPanel2.setMaximumSize(new Dimension(250,22));
		
		
		clabel = new JLabel("Green");
		clabel.setSize(40,22);
		clabel.setPreferredSize(new Dimension(40,22));
		clabel.setMinimumSize(new Dimension(40,22));
		clabel.setMaximumSize(new Dimension(40,22));
		
		colorNumber2 = new JLabel("100");
		colorNumber2.setSize(40,22);
		colorNumber2.setPreferredSize(new Dimension(40,22));
		colorNumber2.setMinimumSize(new Dimension(40,22));
		colorNumber2.setMaximumSize(new Dimension(40,22));
		
		slider2 = new JScrollBar(Scrollbar.HORIZONTAL, 100, 0, 0, 255);
		slider2.addAdjustmentListener(adjHandle);
		
		sliderPanel2.add(clabel);
		sliderPanel2.add(slider2);
		sliderPanel2.add(colorNumber2);
		
		// the BLUE slider panel
		JPanel sliderPanel3 = new JPanel();
		sliderPanel3.setLayout(new BoxLayout(sliderPanel3,BoxLayout.LINE_AXIS));
		sliderPanel3.setSize(250,22);
		sliderPanel3.setPreferredSize(new Dimension(250,22));
		sliderPanel3.setMinimumSize(new Dimension(250,22));
		sliderPanel3.setMaximumSize(new Dimension(250,22));
		
		clabel = new JLabel("Blue");
		clabel.setSize(40,22);
		clabel.setPreferredSize(new Dimension(40,22));
		clabel.setMinimumSize(new Dimension(40,22));
		clabel.setMaximumSize(new Dimension(40,22));
		
		colorNumber3 = new JLabel("100");
		colorNumber3.setSize(40,22);
		colorNumber3.setPreferredSize(new Dimension(40,22));
		colorNumber3.setMinimumSize(new Dimension(40,22));
		colorNumber3.setMaximumSize(new Dimension(40,22));
		
		slider3 = new JScrollBar(Scrollbar.HORIZONTAL, 100, 0, 0, 255);
		slider3.addAdjustmentListener(adjHandle);
		
		sliderPanel3.add(clabel);
		sliderPanel3.add(slider3);
		sliderPanel3.add(colorNumber3);
		
		JPanel buttonsPanel = new JPanel(new FlowLayout());
		back = new JButton("Back");
		back.addActionListener(actHandle);
		back.setToolTipText("Go back one sample.");
		next = new JButton("Next");
		next.addActionListener(actHandle);
		next.setToolTipText("Go to next sample.");
		resetSliders = new JButton("Reset");
		resetSliders.addActionListener(actHandle);
		resetSliders.setToolTipText("Reset the sliders.");
		
		buttonsPanel.add(back);
		buttonsPanel.add(next);
		buttonsPanel.add(resetSliders);
		
		upLeft.add(sliderPanel1);
		upLeft.add(sliderPanel2);
		upLeft.add(sliderPanel3); 
		upLeft.add(buttonsPanel);
		
		return upLeft;
	}
	
	// build the up right panel of tab2
	private JPanel buildUpRightInTab2(){
		JPanel upRight = new JPanel();
		upRight.setLayout(new FlowLayout());
		upRight.setBorder(BorderFactory.createCompoundBorder(
				BorderFactory.createTitledBorder("Color Compare"),
				BorderFactory.createEmptyBorder(0, 8, 8, 8)));
		
		colorBlock = new JPanel();
		colorBlock.setBorder(BorderFactory.createEtchedBorder());
		colorBlock.setSize(80,120);
		colorBlock.setPreferredSize(new Dimension(80,120));
		colorBlock.setMinimumSize(new Dimension(80,120));
		colorBlock.setMaximumSize(new Dimension(80,120));
		
		emptyColorblock = new JPanel();
		emptyColorblock.setBorder(BorderFactory.createEtchedBorder());
		emptyColorblock.setBackground(Color.WHITE);
		emptyColorblock.setSize(80,120);
		emptyColorblock.setPreferredSize(new Dimension(80,120));
		emptyColorblock.setMinimumSize(new Dimension(80,120));
		emptyColorblock.setMaximumSize(new Dimension(80,120));
		
		upRight.add(colorBlock);
		upRight.add(emptyColorblock);
		
		return upRight;
	}
	
	// build the down left panel of tab2
	private JPanel buildDownInTab2(){
		JPanel downLeft = new JPanel();
		downLeft.setLayout(new BorderLayout());
		downLeft.setBorder(BorderFactory.createCompoundBorder(
				BorderFactory.createTitledBorder("Results"),
				BorderFactory.createEmptyBorder(0, 8, 8, 8)));
		
		JPanel xyzPanel = new JPanel(new GridLayout(3,3));
		//xyzPanel.setSize(72,72);
		
		JPanel rgbPanel = new JPanel(new GridLayout(3,3));
		//rgbPanel.setSize(72,72);
		
		JPanel primariesPanel = new JPanel(new GridLayout(3,3));
		//primariesPanel.setSize(72,72);
		
		JPanel upPanel = new JPanel(new FlowLayout());
		JPanel buttonsPanel = new JPanel(new FlowLayout());
		
		
		xyzField = new JTextField[3][3];
		rgbField = new JTextField[3][3];
		primariesField = new JTextField[3][3];
		
		Dimension d = new Dimension(50,22);
		for(int i=0; i<mHeight; i++){
			for(int j=0; j<mWidth; j++){
				xyzField[i][j] = new JTextField(i + "" + j);
				xyzField[i][j].setSize(d);
				xyzField[i][j].setMaximumSize(d);
				xyzField[i][j].setMinimumSize(d);
				xyzField[i][j].setPreferredSize(d);
				
				xyzPanel.add(xyzField[i][j]);
				
				primariesField[i][j] = new JTextField(/*i + */" ? "/* + j*/);
				primariesField[i][j].setSize(d);
				primariesField[i][j].setMaximumSize(d);
				primariesField[i][j].setMinimumSize(d);
				primariesField[i][j].setPreferredSize(d);
				
				primariesPanel.add(primariesField[i][j]);
				
				rgbField[i][j] = new JTextField(i + "" + j);
				rgbField[i][j].setSize(d);
				rgbField[i][j].setMaximumSize(d);
				rgbField[i][j].setMinimumSize(d);
				rgbField[i][j].setPreferredSize(d);
				
				rgbPanel.add(rgbField[i][j]);	
			}
		}
		
		compute = new JButton("Compute");
		compute.addActionListener(actHandle);
		compute.setToolTipText("Compute the monitor matrix.");
		//setXYZ = new JButton("Set xyz");
		
		JLabel eq = new JLabel(" = ");
		JLabel mult = new JLabel( " * ");
		
		upPanel.add(xyzPanel);
		upPanel.add(eq);
		upPanel.add(primariesPanel);
		upPanel.add(mult);
		upPanel.add(rgbPanel);
				
		gammaLabelTab2 = new JLabel("The Gamma is: ?");
		
		buttonsPanel.add(compute);
		
		downLeft.add(upPanel,BorderLayout.CENTER);
		downLeft.add(buttonsPanel, BorderLayout.LINE_END);
		downLeft.add(gammaLabelTab2,BorderLayout.PAGE_END);
		
		return downLeft;
	}
	
	/**
	 * Delivers the RGB data to the matlab or any other external program
	 * or function.
	 * Note:
	 * 	before using that function it is stronglyl recomended to check 
	 * 	whether the data is teady or not with the function:
	 * 		isDataReady();
	 */ 
	public double[][] getXYZValues(){
		return xyzValues;
	}
	
	/**
	 * Delivers the XYZ data to the matlab or any other external program
	 * or function.
	 * Note:
	 * 	before using that function it is stronglyl recomended to check 
	 * 	whether the data is teady or not with the function:
	 * 		isDataReady();
	 */ 
	public double[][] getRGBValues(){
		return rgbValues;
	}
	
	/**
	 * Delivers the GAMMA data to the matlab or any other external program
	 * or function.
	 * Note:
	 * 	before using that function it is stronglyl recomended to check 
	 * 	whether the data is teady or not with the function:
	 * 		isDataReady();
	 */ 
	public double getGamma(){
		return gammaValue;
	}
	
	/** Returns the program state - is data accepeted from the user is
	 *  ready or not
	 */
	public boolean isDataReady(){
		return dataReady;
	}
	
	/** Solves the equation A=X*B where A,B and X are Matrixes and 
	 *  X in dont known */
	public void computePrimariesData(){
		
		// gamma_rgb = (((double(rgb))./255).^gamma).*255
		Matrix rgbGammaTempMatrix = new Matrix(
				powMatrix(divByConst(rgbValues,255), gammaValue));
		
		double[][] temp = rgbGammaTempMatrix.getArray();
		Matrix rgbGammaMatrix = new Matrix(mulByConst(temp,255));
		
		//p_inv_rgb = pinv(gamma_rgb) % find the pseudoinverce matrix
		//M = double(xyz)*p_inv_rgb   % find the wanted matrix transform
		Matrix xyzMatrix = new Matrix(xyzValues);
		primariesValues = xyzMatrix.times(rgbGammaMatrix.inverse()).getArray();
		
		// Set the data to the gui fields
		setPrimariesData(primariesValues);
		
		canvasLabel.resetGammutPoints();
		
		// Draw the data 
		/* Original
		canvasLabel.drawPrimaries(
		        Double.parseDouble(primariesField[0][0].getText()),
				Double.parseDouble(primariesField[0][1].getText()),
				Double.parseDouble(primariesField[0][2].getText()));
		
		canvasLabel.drawPrimaries(
		        Double.parseDouble(primariesField[1][0].getText()),
				Double.parseDouble(primariesField[1][1].getText()),
				Double.parseDouble(primariesField[1][2].getText()));
		canvasLabel.drawPrimaries(
		        Double.parseDouble(primariesField[2][0].getText()),
				Double.parseDouble(primariesField[2][1].getText()),
				Double.parseDouble(primariesField[2][2].getText()));
		
		**/
//		 Draw the data 
		canvasLabel.drawPrimaries(
		        Double.parseDouble(primariesField[0][0].getText()),
				Double.parseDouble(primariesField[1][0].getText()),
				Double.parseDouble(primariesField[2][0].getText()));
		
		canvasLabel.drawPrimaries(
		        Double.parseDouble(primariesField[0][1].getText()),
				Double.parseDouble(primariesField[1][1].getText()),
				Double.parseDouble(primariesField[2][1].getText()));
		canvasLabel.drawPrimaries(
		        Double.parseDouble(primariesField[0][2].getText()),
				Double.parseDouble(primariesField[1][2].getText()),
				Double.parseDouble(primariesField[2][2].getText()));
		
		// for debugging
		System.out.println(
				"RGB values " + newLine + 
		        " X[0][0] = " + rgbValues[0][0] + 
		        " Y[0][1] = " + rgbValues[0][1] +
		        " Z[0][2] = " + rgbValues[0][2] + newLine +
		        
		        " X[1][0] = " + rgbValues[1][0] + 
		        " Y[1][1] = " + rgbValues[1][1] +
		        " Z[1][2] = " + rgbValues[1][2] + newLine +
		        
		        " X[2][0] = " + rgbValues[2][0] +       
		        " Y[2][1] = " + rgbValues[2][1] +
		        " Z[2][2] = " + rgbValues[2][2] + newLine 
		);
		
		System.out.println(
				"XYZ values " + newLine + 
		        " X[0][0] = " + xyzValues[0][0] + 
		        " Y[0][1] = " + xyzValues[0][1] +
		        " Z[0][2] = " + xyzValues[0][2] + newLine +
		        
		        " X[1][0] = " + xyzValues[1][0] + 
		        " Y[1][1] = " + xyzValues[1][1] +
		        " Z[1][2] = " + xyzValues[1][2] + newLine +
		        
		        " X[2][0] = " + xyzValues[2][0] +       
		        " Y[2][1] = " + xyzValues[2][1] +
		        " Z[2][2] = " + xyzValues[2][2] + newLine 
		);
		
		System.out.println(
				"Primaries values " +
		        " X[0][0] = " + primariesValues[0][0] + 
		        " Y[0][1] = " + primariesValues[0][1] +
		        " Z[0][2] = " + primariesValues[0][2] + newLine +
		        
		        " X[1][0] = " + primariesValues[1][0] + 
		        " Y[1][1] = " + primariesValues[1][1] +
		        " Z[1][2] = " + primariesValues[1][2] + newLine +
		        
		        " X[2][0] = " + primariesValues[2][0] +       
		        " Y[2][1] = " + primariesValues[2][1] +
		        " Z[2][2] = " + primariesValues[2][2] + newLine 
		);
		
		// For debuging
		System.out.println(
				"Primaries: " + newLine +
		        " X[0][0] = " + Double.parseDouble(primariesField[0][0].getText()) + 
		        " Y[0][1] = " + Double.parseDouble(primariesField[0][1].getText()) +
		        " Z[0][2] = " + Double.parseDouble(primariesField[0][2].getText()) + newLine +
		        
		        " X[1][0] = " + Double.parseDouble(primariesField[1][0].getText()) + 
		        " Y[1][1] = " + Double.parseDouble(primariesField[1][1].getText()) +
		        " Z[1][2] = " + Double.parseDouble(primariesField[1][2].getText()) + newLine +
		        
		        " X[2][0] = " + Double.parseDouble(primariesField[2][0].getText()) +       
		        " Y[2][1] = " + Double.parseDouble(primariesField[2][1].getText()) +
		        " Z[2][2] = " + Double.parseDouble(primariesField[2][2].getText()) + newLine 
		);
		//canvasLabel.repaint();
	}
	
	/** Computes the pow matrix where every sell in the matris 
	 *  is powed by p. */
	public double[][] powMatrix(double[][] m, double p){
		
		for(int i=0; i<3; i++){
			for(int j=0; j<3; j++){
				m[i][j] = Math.pow((m[i][j]),p);
			}
		}
		return m;
	}
	
	/** "./" in matlab */
	public double[][] divByConst(double[][] m, double p){
		for(int i=0; i<3; i++){
			for(int j=0; j<3; j++){
				m[i][j] = (m[i][j])/p;
			}
		}
		return m;
	}
	
	/** ".*" in matlab */
	public double[][] mulByConst(double[][] m, double p){
		for(int i=0; i<3; i++){
			for(int j=0; j<3; j++){
				m[i][j] = (m[i][j])*p;
			}
		}
		return m;
	}
	
	/** Converts a double to string */
	private String doubleToString(double val, int digits)
	{
		char sign = (val < 0.0) ? '-' : ' ';
		double aval = Math.abs(val);
		int whole = (int)aval;
		double frac = aval - (double)whole;
		int digit;
		String res;
		
		res = sign + Integer.toString(whole) + ".";
		for (int i=0; i< digits; i++) {
			frac *= 10.0;
			digit = (int)frac;
			frac = frac - (double)digit;
			res += Integer.toString(digit);
		}
		
		return res;
	}
	
	/**
	 * The purpose of that function is to get data from external 
	 * interface like Matlab engine and set the data back in 
	 * to the Java gui.
	 */
	public void setPrimariesData(double[][] p ){
		for(int i=0; i<mHeight; i++){
			for(int j = 0; j<mWidth; j++){
				//primariesValues[i][j] = p[i][j];
				primariesField[i][j].setText(doubleToString(p[i][j],3));
				//System.out.println(doubleToString(p[i][j],3) + " " + p[i][j]);
			}
		}
		this.repaint();
		//this.pack();
	}
	
	/** Prints test string on screen */
	public void printSomething(){
		System.out.println("test !!!!!!!!!!1");
	}
	
	/** Computes the gamma when x = r^gamma */
	public double calcGamma(int match){
		return Math.log(0.5)/Math.log((double)match/255.0);
	}
	
	/** Inner class for listening to buttons events */
	private class ActionEventHandler
	implements ActionListener {
		
		/** Event handling function */
		public void actionPerformed(ActionEvent e) {
			
			//OPEN BUTTON
			if(e.getSource() == next) {
				if(rgbDataCount<3){ 
					rgbField[0][rgbDataCount].setText(Double.toString(
							slider1.getValue()));
					rgbField[1][rgbDataCount].setText(Double.toString(
							slider2.getValue()));
					rgbField[2][rgbDataCount].setText(Double.toString(
							slider3.getValue()));
					
					rgbDataCount++;
				}
				return;
			}
			if(e.getSource() == back){
				if(rgbDataCount>0){
					rgbDataCount--;
					
					rgbField[0][rgbDataCount].setText(" ");
					rgbField[1][rgbDataCount].setText(" ");
					rgbField[2][rgbDataCount].setText(" ");
					dataReady = false;
				}
				
				return;
			}
			if(e.getSource() == resetSliders){
				slider1.setValue(100);
				slider2.setValue(100);
				slider3.setValue(100);
				return;
			}
			if(e.getSource() == compute){
				// NOTE: need to check if all the data is accepted 
				// and then to make that button presseble ~!
				
				// Set the data in to the matrix variables
				for(int i=0; i<mHeight; i++){
					for(int j=0; j<mWidth; j++){
						rgbValues[i][j] = Double.parseDouble(
								rgbField[i][j].getText());
						xyzValues[i][j] = Double.parseDouble(
								xyzField[i][j].getText());
					}
				}
				
				// Call the Java compute function
				computePrimariesData();
				
				dataReady = true;
				
				canvasLabel.updateData(primariesValues,gammaValue);
				
				return;
			}
			if(e.getSource() == setXYZ){
			    
				return;
			}
		}
	}
	
	/** Listens for sliders */
	private class AdjustmentEventListener 
	implements AdjustmentListener{
		
		// When any of the sliders are changed this will refresh
		// the contents of the applet.
		public void adjustmentValueChanged(AdjustmentEvent e) {
			if(e.getSource() == slider1){  	
				if((slider1.getValue()<256) & (slider2.getValue()<256) & (
						slider3.getValue()<256)){
					Color blockColor = new Color(slider1.getValue(),
							slider2.getValue(),slider3.getValue());
					colorBlock.setBackground(blockColor);
					colorNumber1.setText(Integer.toString(slider1.getValue()));
				}
				return;
			}
			if(e.getSource() == slider2){
				if((slider1.getValue()<256) & (slider2.getValue()<256) & (
						slider3.getValue()<256)){
					Color blockColor = new Color(slider1.getValue(),
							slider2.getValue(),slider3.getValue());
					colorBlock.setBackground(blockColor);
					colorNumber2.setText(Integer.toString(slider2.getValue()));
				} 
				return;
			}
			if(e.getSource() == slider3){
				if((slider1.getValue()<256) & (slider2.getValue()<256) & (
						slider3.getValue()<256)){
					Color blockColor = new Color(slider1.getValue(),
							slider2.getValue(),slider3.getValue());
					colorBlock.setBackground(blockColor);
					colorNumber3.setText(Integer.toString(slider3.getValue()));
				} 
				return;
			}
			if(e.getSource() == gammaSlider){
				//c_right.match = 255 - bar.getValue();
				//gamma_label.setText("Gamma: " +
				//        doubleToString(CalcGamma(c_right.match), 2));
				//c_right.repaint();
				gammaCanvas.setGrayLvl(255 - gammaSlider.getValue());
				
				// calculate the gamma of the screen
				gammaLabelTab1.setText("Your Gamma is:" + " " + doubleToString(
						calcGamma(gammaCanvas.getGrayLvl()),2));
				gammaLabelTab2.setText("Your Gamma is:" + " " + doubleToString(
						calcGamma(gammaCanvas.getGrayLvl()),2));
				gammaValue = Double.parseDouble(doubleToString(calcGamma(
						gammaCanvas.getGrayLvl()),2));
				gammaCanvas.repaint();
				
				setRgbGamaImage();
				
				//ditheredCanvas.repaint();
				return;
			}
		}
		
	}
	
	/** Listens for component chenges to adjust the gui alinment */
	private class ComponentEventListener 
	implements ComponentListener{
		public void componentResized(ComponentEvent e) {
			//refresh();
		}
		
		public void componentHidden(ComponentEvent e) {
			//refresh();
		}
		
		public void componentMoved(ComponentEvent e) {
			// refresh();
		}
		
		public void componentShown(ComponentEvent e) {
			//refresh();
		}
	}

}
